using System;
using System.Collections.Generic;
using System.Text;

// Assemblies needed for database stuff
using System.Data;
using System.Data.Common;
using System.Data.SQLite;

using System.Text.RegularExpressions;

namespace BibleSQL
{
    enum Books
    {
        Genesis = 1, Exodus, Leviticus, Numbers, Deuteronomy, Joshua, Judges, Ruth, First_Samuel, Second_Samuel,
        First_Kings, Second_Kings, First_Chronicles, Second_Chronicles, Ezra, Nehemiah, Esther, Job, Psalms, Proverbs, 
        Ecclesiastes, Song_of_Solomon, Isaiah, Jeremiah, Lamentations, Ezekiel, Daniel, Hosea, Joel, 
        Amos, Obadiah, Jonah, Micah, Nahum, Habakkuk, Zephaniah, Haggai, Zechariah, Malachi, Matthew, 
        Mark, Luke, John, Acts_of_the_Apostles, Romans, First_Corinthians, Second_Corinthians, Galatians, 
        Ephesians, Philippians, Colossians, First_Thessalonians, Second_Thessalonians, First_Timothy, Second_Timothy, 
        Titus, Philemon, Hebrews, James, First_Peter, Second_Peter, First_John, Second_John, Third_John, Jude, Revelation
    }

    public class ErrorEventArgs: EventArgs
    {
        public string Message;
        public ErrorEventArgs(string Message)
        {
            this.Message = Message;
        }
    }

    public class BibleSQL
    {
        public delegate void ErrorEventDelegate(object sender, ErrorEventArgs e);
        public event ErrorEventDelegate Error;

        public delegate void PositionChangedEventDelegate(object sender, EventArgs e);
        public event PositionChangedEventDelegate PositionChanged;

        const string TableName = "Bible";
        DataTable table;
        DataTable Table
        {
            get { return table; }
        }
        int _index = 0;
        int index
        {
            get
            {
                return _index;
            }
            set
            {
                _index = value;
                OnPositionChanged(new EventArgs());
            }
        }
        public string Book
        {
            get
            {
                if (table != null)
                {
                    int bookNum = int.Parse(table.Rows[index]["Book ID"].ToString());
                    return ((Books)bookNum).ToString().Replace('_', ' ');
                }
                else
                    return null;
            }
            set 
            {
                value = value.Replace(' ', '_');
                int bookID = (int)Enum.Parse(typeof(Books), value);
                DataRow[] rows = table.Select("[Book ID] = " + bookID.ToString());
                if (rows.Length > 0)
                    index = Convert.ToInt32(rows[0]["ID"]) - 1;
            }
        }
        public int Chapter
        {
            get
            {
                if (table != null)
                    return Convert.ToInt32(table.Rows[index]["Chapter"]);
                else
                    return 0;
            }
            set 
            {
                DataRow currentRow = table.Rows[index];
                int bookID = Convert.ToInt32(currentRow["Book ID"]);
                DataRow[] rows = table.Select(string.Format("[Book ID] = {0} AND Chapter = {1}", bookID, value));
                if (rows.Length > 0)
                    index = Convert.ToInt32(rows[0]["ID"]) - 1;
            }
        }
        public int Verse
        {
            get
            {
                if (table != null)
                    return Convert.ToInt32(table.Rows[index]["Verse"]);
                else
                    return 0;
            }
            set 
            {
                DataRow currentRow = table.Rows[index];
                int bookID = Convert.ToInt32(currentRow["Book ID"]);
                DataRow[] rows = table.Select(string.Format("[Book ID] = {0} AND Chapter = {1} AND Verse = {2}", bookID, Chapter, value));
                if (rows.Length > 0)
                    index = Convert.ToInt32(rows[0]["ID"]) - 1;
            }
        }
        public string Scripture
        {
            get
            {
                if (table != null)
                {
                    string s = table.Rows[index]["Scripture"].ToString();
                    // Regex to get rid of the italic and color emphasis tags (eg. '{\cf15\I it was}')

                    s = Regex.Replace(s, @"{\\cf15\\I (?<text>.*?)}", delegate(Match m) 
                                                                        { return m.Groups["text"].Value; });
                    return s;
                }
                else
                    return null;
            }
        }
        public string Position
        {
            get
            {
                if (table != null)
                    return String.Format("{0}, Chapter {1}, Verse {2}", Book, Chapter, Verse);
                else
                    return null;
            }
        }

        public BibleSQL(string bibleDB)
        {
            SQLiteConnection conn = new SQLiteConnection();
            try
            {
                // Connect to the database and get the "Bible" table
                string connString = String.Format("Data Source={0};Version=3;", bibleDB);
                conn.ConnectionString = connString;
                conn.Open();
                SQLiteDataAdapter adapter = new SQLiteDataAdapter("SELECT * FROM " + TableName, conn);
                DataSet dataSet = new DataSet();
                adapter.Fill(dataSet, TableName);
                table = dataSet.Tables[TableName];
            }
            catch (Exception e)
            {
                // Call Error event handlers
                OnError(new ErrorEventArgs(e.Message));
            }
            finally
            {
                conn.Close();
            }
        }

        protected virtual void OnError(ErrorEventArgs e)
        {
            if (Error != null)
                Error(this, e);
        }

        protected virtual void OnPositionChanged(EventArgs e)
        {
            if (PositionChanged != null)
                PositionChanged(this, e);
        }

        void IncrementIndex()
        {
            _index++;
            if (_index >= table.Rows.Count)
                _index = 0;
            index = _index;
        }

        void DecrementIndex()
        {
            _index--;
            if (_index < 0)
                _index = table.Rows.Count - 1;
            index = _index;
        }

        public void NextBook()
        {
            if (table != null)
            {
                string currentBook = Book;
                while (currentBook == Book)
                    IncrementIndex();
            }
        }

        public void PrevBook()
        {
            if (table != null)
            {
                string currentBook = Book;
                while (currentBook == Book)
                    DecrementIndex();
                // Set index to start of book
                Book = Book;
            }
        }

        public void NextChapter()
        {
            if (table != null)
            {
                int currentChapter = Chapter;
                while (currentChapter == Chapter)
                    IncrementIndex();
            }
        }

        public void PrevChapter()
        {
            if (table != null)
            {
                int currentChapter = Chapter;
                while (currentChapter == Chapter)
                    DecrementIndex();
                // Set index to start of chapter
                Chapter = Chapter;
            }
        }

        public void NextVerse()
        {
            if (table != null)
            {
                int currentVerse = Verse;
                while (currentVerse == Verse)
                    IncrementIndex();
            }
        }

        public void PrevVerse()
        {
            if (table != null)
            {
                int currentVerse = Verse;
                while (currentVerse == Verse)
                    DecrementIndex();
            }
        }
    }
}
